// 哔哩哔哩缓存文件我见到的有两种--blv，m4s，针对不同的格式有不同的转换器
package converter

import (
	"log"
	"os"
	"sync"
)

type VideoType int

const (
	NONE VideoType = iota
	M4S
	BLV
)

// 转换器定义
type Converter func(cacheVideoDir *CacheVideoDir, targetPath, temp string)

// ConverterMap 转换器的map
var Maps = make(map[VideoType]Converter, 2)
var MapNames = make(map[VideoType]string, 2)

// 像ConverterMap注册Converter
func Register(videoType VideoType, name string, converter Converter) {
	Maps[videoType] = converter
	MapNames[videoType] = name
}

// Convert 开始进行数据转换
func Convert(command *Command, cacheVideoDirSlice [][]*CacheVideoDir) {
	if len(cacheVideoDirSlice) == 0 {
		log.Printf("cacheVideoDirSlice 没有待转换的视频数据\n")
		return
	}
	group := sync.WaitGroup{}
	wrapsChan := make(chan *datumWrap, 3)
	for i := 0; i < int(command.Num); i++ {
		group.Add(1)
		go invokeConverter(wrapsChan, &group)
	}
	for _, cacheVideoDirs := range cacheVideoDirSlice {
		for _, cacheVideoDir := range cacheVideoDirs {
			converter, ok := Maps[cacheVideoDir.Type]
			if !ok || converter == nil {
				name := MapNames[cacheVideoDir.Type]
				if name != "" {
					log.Printf("没有可以转换 %s 的转换器", name)
				} else {
					log.Printf("type %d 没有对应的转换器", cacheVideoDir.Type)
				}
				continue
			}
			wrapsChan <- &datumWrap{converter: converter, cacheVideoDir: cacheVideoDir, targetPath: command.Target, tempPath: command.TempPath}
		}
	}
	close(wrapsChan)
	group.Wait()
}

func invokeConverter(ch <-chan *datumWrap, group *sync.WaitGroup) {
	for datumWrap := range ch {
		datumWrap.converter(datumWrap.cacheVideoDir, datumWrap.targetPath, datumWrap.tempPath)
	}
	group.Done()
}

type datumWrap struct {
	converter     Converter
	cacheVideoDir *CacheVideoDir
	targetPath    string
	tempPath      string
}

func MkdirAllDir(path string) bool {
	if file, e := os.Open(path); e != nil {
		if !os.IsNotExist(e) {
			log.Println("create file error :", e.Error())
			return false
		} else {
			log.Printf("正在创建文件夹 %s\n", path)
			e = os.MkdirAll(path, os.ModePerm)
			if e != nil {
				if !os.IsExist(e) {
					log.Printf("创建文件夹 %s 失败：%s\n", path, e.Error())
					return false
				} else {
					MkdirAllDir(path)
				}
			}
		}
	} else {
		defer file.Close()
		info, e := file.Stat()
		if e != nil {
			log.Printf("文件夹 %s 获取信息失败：%s\n", path, e.Error())
			return false
		}
		if !info.IsDir() {
			log.Printf("%s 不是一个文件夹\n", path)
			return false
		}
	}
	return true
}
